package com.ohos.connect.devicecloud.app.modular.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fhs.trans.service.impl.TransService;
import com.ohos.connect.devicecloud.app.modular.project.model.entity.Project;
import com.ohos.connect.devicecloud.app.modular.project.service.ProjectService;
import com.ohos.connect.devicecloud.app.modular.projectuser.model.entity.ProjectUser;
import com.ohos.connect.devicecloud.app.modular.projectuser.service.ProjectUserService;
import com.ohos.connect.devicecloud.app.modular.user.model.dto.*;
import com.ohos.connect.devicecloud.app.modular.user.model.vo.AppUserInfoVO;
import com.ohos.connect.devicecloud.auth.api.AppUserAuthApi;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ohos.connect.devicecloud.app.modular.user.model.entity.AppUser;
import com.ohos.connect.devicecloud.app.modular.user.enums.AppUserStatusEnum;
import com.ohos.connect.devicecloud.app.modular.user.mapper.AppUserMapper;
import com.ohos.connect.devicecloud.app.modular.user.model.vo.AppLoginUserVO;
import com.ohos.connect.devicecloud.app.modular.user.service.AppUserService;
import com.ohos.connect.devicecloud.common.enums.CommonSortOrderEnum;
import com.ohos.connect.devicecloud.common.exception.CommonException;
import com.ohos.connect.devicecloud.common.page.CommonPageRequest;
import com.ohos.connect.devicecloud.common.util.*;

import javax.annotation.Resource;
import java.util.List;

/**
 * APP用户Service接口实现类
 **/
@Service
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {

    private static final String OHOS_CONNECT_DEVICE_CLOUD_SYS_DEFAULT_PASSWORD_KEY = "OHOS_CONNECT_DEVICE_CLOUD_SYS_DEFAULT_PASSWORD";

    @Resource
    private TransService transService;

    @Resource
    private AppUserAuthApi appUserAuthApi;

    @Resource
    private ProjectService projectService;

    @Resource
    private ProjectUserService projectUserService;

    @Override
    public AppLoginUserVO getUserById(String id) {
        AppUser appUser = this.getById(id);
        if(ObjectUtil.isNotEmpty(appUser)) {
            transService.transOne(appUser);
            return BeanUtil.copyProperties(appUser, AppLoginUserVO.class);
        }
        return null;
    }

    @Override
    public AppLoginUserVO getUserByAccount(String account) {
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getAccount, account));
        if(ObjectUtil.isNotEmpty(appUser)) {
            transService.transOne(appUser);
            return BeanUtil.copyProperties(appUser, AppLoginUserVO.class);
        }
        return null;
    }

    @Override
    public AppLoginUserVO getUserByPhone(String phone) {
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, phone));
        if(ObjectUtil.isNotEmpty(appUser)) {
            transService.transOne(appUser);
            return BeanUtil.copyProperties(appUser, AppLoginUserVO.class);
        }
        return null;
    }

    @Override
    public AppLoginUserVO getUserByEmail(String email) {
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getEmail, email));
        if(ObjectUtil.isNotEmpty(appUser)) {
            transService.transOne(appUser);
            return BeanUtil.copyProperties(appUser, AppLoginUserVO.class);
        }
        return null;
    }

    @Override
    public Page<AppUser> page(AppUserPageDTO appUserPageDTO) {
        QueryWrapper<AppUser> queryWrapper = new QueryWrapper<>();
        if(ObjectUtil.isNotEmpty(appUserPageDTO.getSearchKey())) {
            queryWrapper.lambda().and(q -> q.like(AppUser::getNickname, appUserPageDTO.getSearchKey())
                    .or().like(AppUser::getAccount, appUserPageDTO.getSearchKey()));
        }
        if(ObjectUtil.isAllNotEmpty(appUserPageDTO.getSortField(), appUserPageDTO.getSortOrder())) {
            CommonSortOrderEnum.validate(appUserPageDTO.getSortOrder());
            queryWrapper.orderBy(true, appUserPageDTO.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(appUserPageDTO.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(AppUser::getCreateTime);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean insert(AppUserInsertDTO appUserInsertDTO) {
        // 校验手机号、账号、密码
        checkParam(appUserInsertDTO);

        // 校验手机号验证码
        appUserAuthApi.validPhoneCode(appUserInsertDTO.getPhone(),appUserInsertDTO.getValidCode(),appUserInsertDTO.getValidCodeReqNo());
        AppUser appUser = BeanUtil.toBean(appUserInsertDTO, AppUser.class);
        // 设置密码
//        clientUser.setPassword(CommonCryptogramUtil.doHashValue(devConfigApi.getValueByKey(OHOS_CONNECT_DEVICE_CLOUD_SYS_DEFAULT_PASSWORD_KEY)));
        appUser.setPassword(CommonCryptogramUtil.doHashValue(appUserInsertDTO.getPassword()));
        // 设置状态
        appUser.setUserStatus(AppUserStatusEnum.ENABLE.getValue());
        boolean insertApp = this.save(appUser);
        if(!insertApp){
            throw new CommonException("新增用户失败");
        }

        // 创建完APP帐号后，创建一个默认的项目
        Project project = new Project();
        project.setName("我的项目");
        boolean insertDefaultProject = projectService.save(project);
        if(!insertDefaultProject){
            throw new CommonException("创建默认项目失败");
        }

        // 将默认项目与APP用户绑定
        ProjectUser projectUser = new ProjectUser();
        projectUser.setAppUserId(appUser.getId());
        projectUser.setProjectId(project.getId());
        boolean insertDefaultProjectUser = projectUserService.save(projectUser);
        if(!insertDefaultProjectUser){
            throw new CommonException("将默认项目与APP用户绑定失败");
        }

        return Boolean.TRUE;
    }

    private void checkParam(AppUserInsertDTO appUserInsertDTO) {
        if (this.count(new LambdaQueryWrapper<AppUser>()
                .eq(AppUser::getAccount, appUserInsertDTO.getAccount())) > 0) {
            throw new CommonException("存在重复的账号，账号为：{}", appUserInsertDTO.getAccount());
        }
        if(ObjectUtil.isNotEmpty(appUserInsertDTO.getPhone())) {
            if(!PhoneUtil.isMobile(appUserInsertDTO.getPhone())) {
                throw new CommonException("手机号码：{}格式错误", appUserInsertDTO.getPhone());
            }
            if (this.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getPhone, appUserInsertDTO.getPhone())) > 0) {
                throw new CommonException("存在重复的手机号，手机号为：{}", appUserInsertDTO.getPhone());
            }
        }else{
            throw new CommonException("手机号不能为空!");
        }

        if(ObjectUtil.isEmpty(appUserInsertDTO.getPassword())) {
            throw new CommonException("密码不能为空!");
        }

    }

    @Override
    public Boolean edit(AppUserEditDTO appUserEditDTO) {
        AppUser appUser = this.queryEntityByAccount(appUserEditDTO.getAccount());
        checkParam(appUserEditDTO);

        // 手机号
        if(ObjectUtil.isNotEmpty(appUserEditDTO.getPhone())) {
            appUser.setPhone(appUserEditDTO.getPhone());
        }
        // 密码
        if(ObjectUtil.isNotEmpty(appUserEditDTO.getPassword())) {
            appUser.setPassword(CommonCryptogramUtil.doHashValue(appUserEditDTO.getPassword()));
        }
        // 头像
        if(ObjectUtil.isNotEmpty(appUserEditDTO.getAvatar())){
            appUser.setAvatar(appUserEditDTO.getAvatar());
        }
        // 邮件
        if(ObjectUtil.isNotEmpty(appUserEditDTO.getEmail())) {
            appUser.setEmail(appUserEditDTO.getEmail());
        }
        // 昵称
        if(ObjectUtil.isNotEmpty(appUserEditDTO.getNickname())) {
            appUser.setNickname(appUserEditDTO.getNickname());
        }

        return this.updateById(appUser);
    }

    @Override
    public Boolean bindEmail(AppUserEmailDTO appUserEmailDTO){
        // 校验邮箱
        checkEmail(appUserEmailDTO.getEmail());

        // 校验手机号验证码
        appUserAuthApi.validPhoneCode(appUserEmailDTO.getEmail(),appUserEmailDTO.getValidCode(),appUserEmailDTO.getValidCodeReqNo());

        AppUser appUser = this.queryEntityByAccount(appUserEmailDTO.getAccount());
        appUser.setEmail(appUserEmailDTO.getEmail());
        // 设置状态
        return this.updateById(appUser);
    }

    private void checkEmail(String email){
        if(ObjectUtil.isNotEmpty(email)) {
            if(!CommonEmailUtil.isEmail(email)) {
                throw new CommonException("邮箱：{}格式错误", email);
            }
            if (this.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getEmail, email)) > 0) {
                throw new CommonException("存在重复的邮箱，邮箱为：{}", email);
            }
        }
    }

    private void checkParam(AppUserEditDTO appUserEditDTO) {

        if(ObjectUtil.isNotEmpty(appUserEditDTO.getPhone())) {
            if(!PhoneUtil.isMobile(appUserEditDTO.getPhone())) {
                throw new CommonException("手机号码：{}格式错误", appUserEditDTO.getPhone());
            }
            if (this.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getPhone, CommonCryptogramUtil.doSm4CbcEncrypt(appUserEditDTO.getPhone()))
                    ) > 0) {
                throw new CommonException("存在重复的手机号，手机号为：{}", appUserEditDTO.getPhone());
            }
        }
        if(ObjectUtil.isNotEmpty(appUserEditDTO.getEmail())) {
            if(!CommonEmailUtil.isEmail(appUserEditDTO.getEmail())) {
                throw new CommonException("邮箱：{}格式错误", appUserEditDTO.getEmail());
            }
            if (this.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getEmail, appUserEditDTO.getEmail())
                    ) > 0) {
                throw new CommonException("存在重复的邮箱，邮箱为：{}", appUserEditDTO.getEmail());
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<AppUserAccountDTO> appUserAccountDTOList) {
        this.removeByIds(CollStreamUtil.toList(appUserAccountDTOList, AppUserAccountDTO::getAccount));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteByAccount(String account) {
        AppUser appUser = queryEntityByAccount(account);
        return this.removeById(appUser);
    }

    @Override
    public AppUserInfoVO detail(AppUserAccountDTO appUserAccountDTO) {
        AppUser appUser = this.queryEntityByAccount(appUserAccountDTO.getAccount());
        return BeanUtil.copyProperties(appUser, AppUserInfoVO.class);
    }

    @Override
    public AppUserInfoVO detailByPhone(AppUserPhoneDTO appUserPhoneDTO) {

        LambdaQueryWrapper<AppUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotEmpty(appUserPhoneDTO.getPhone()), AppUser::getPhone, appUserPhoneDTO.getPhone());
        List<AppUser> appUsers = this.list(queryWrapper);

        if(ObjectUtil.isEmpty(appUsers)) {
            throw new CommonException("用户不存在，手机号为：{}", appUserPhoneDTO.getPhone());
        }

        if(appUsers.size() > 1){
            throw new CommonException("同一手机号存在多个用户，手机号为：{}", appUserPhoneDTO.getPhone());
        }

        return BeanUtil.copyProperties(appUsers.get(0), AppUserInfoVO.class);
    }

    @Override
    public void updateUserLoginInfo(String userId, String device) {
        AppUser appUser = this.getById(userId);
        appUser.setLastLoginTime(appUser.getLatestLoginTime());
        appUser.setLastLoginIp(appUser.getLatestLoginIp());
        appUser.setLastLoginAddress(appUser.getLatestLoginAddress());
        appUser.setLastLoginDevice(appUser.getLatestLoginDevice());
        appUser.setLatestLoginTime(DateTime.now());
        String ip = CommonIpAddressUtil.getIp(CommonServletUtil.getRequest());
        appUser.setLatestLoginIp(ip);
        appUser.setLatestLoginAddress(CommonIpAddressUtil.getCityInfo(ip));
        appUser.setLatestLoginDevice(device);
        this.updateById(appUser);
    }

    @Override
    public AppUser queryEntityByAccount(String account) {
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getAccount, account));

        if(ObjectUtil.isEmpty(appUser)) {
            throw new CommonException("用户不存在，账号值为：{}", account);
        }
        return appUser;
    }
}
